#This program will slice an image into small blocks(tiles) and process it 
#To run the code use the following command
#mpiexec -np 5 python mpionimage.py
#Replace the number 5 with no_cores+1

import slicer as sl
import numpy as np
from PIL import Image
from mpi4py import MPI
import numpy


#This function will process an image tile
def process_image(array):
	for i in range(array.shape[0]):
		for j in range(array.shape[1]):
			if array[i,j]>100:
				array[i,j]=0
	return array

comm = MPI.COMM_WORLD
rank = comm.Get_rank()
no_processes=comm.size

#Rank 0 (master) will divide image into tiles and send it to all other process
if comm.rank==0:
	tiles=sl.slice("lena.png",no_processes-1, save=False)
	slave=1
	for tile in tiles:
		array=np.array(tile.image)
		comm.send(array.shape,dest=slave, tag=12)
		comm.Send(array, dest=slave, tag=13)
		slave=slave+1
#All other programs will receive the size of tile and tile
else :
	array_size=comm.recv(source=0, tag=12)
	array = numpy.zeros(array_size, dtype=numpy.uint8)
	comm.Recv(array,source=0, tag=13)
	array=process_image(array)
	
	comm.send(array.shape,dest=0, tag=18)
	comm.Send(array, dest=0, tag=19)
#Master will gather all tiles and join it as single image
if comm.rank==0:
	out=[]
	for i in range(1,no_processes):
		array_size=comm.recv(source=i, tag=18)
		array = numpy.zeros(array_size, dtype=numpy.uint8)
		comm.Recv(array,source=i, tag=19)
		out.append(array)
	index=0
	for out_array in out:
		tiles[index].image=Image.fromarray(out_array)
		index=index+1
	image=sl.join(tiles)
	image.save("outp.png")



